package com.infolab.aims.domain.purchase;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.FactoryUtils;
import org.apache.commons.collections.list.LazyList;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.validator.constraints.NotBlank;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import com.infolab.aims.GlobalConstant;
import com.infolab.aims.common.SpecialMuLineToStringStyle;
import com.infolab.aims.common.SpecialToStringStyle;
import com.infolab.aims.common.bean.AbstractModelBean;
import com.infolab.aims.domain.Department;
import com.infolab.aims.domain.Location;
import com.infolab.aims.domain.Vendor;
import com.infolab.aims.domain.asset.AssetModel;

@Entity
@Table(name="AMTB_PURCHASEORDER")
public class PurchaseOrder extends AbstractModelBean {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer purchaseOrderId;

	@Column(length=10)
	@NotBlank(message="{error.empty}")
	private String assetType;
	
	@NotBlank(message="{error.empty}")
	@Column(unique=true)
	private String purchaseOrderCode;
	
	@NotBlank(message="{error.empty}")
	private String purchaseOrderType;
	
	private String purchaseOrderStatus;

	@NotNull(message="{error.empty}")
	private Date purchaseOrderDate;

	private String companyCode;
	
	public String getCompanyCode() {
		return companyCode;
	}

	public void setCompanyCode(String companyCode) {
		this.companyCode = companyCode;
	}

	@ManyToOne
	@JoinColumn(name="vendorId")
	@NotNull(message="{error.empty}")
	private Vendor vendor;
	
	@ManyToOne
	@JoinColumn(name="accessDepartmentId")
	private Department accessDepartment;
	
	/**
	 * for new purchase order, equipment and component is not used
	 * for equipment repair purchase order, location should be assumed as from location and 
	 * will be used as search location for serial no 
	 */
	@ManyToOne
	@JoinColumn(name="locationId")
	@NotNull(message="{error.empty}")
	private Location location;
	
	
	@Transient
	private List<PurchaseOrderDetail> purchaseOrderDetails = LazyList.decorate(new ArrayList(),
		      FactoryUtils.instantiateFactory(PurchaseOrderDetail.class));

	@Transient
	private List<PurchaseOrderRepair> purchaseOrderRepairs = LazyList.decorate(new ArrayList(),
			  FactoryUtils.instantiateFactory(PurchaseOrderRepair.class));

	@Version 
	private int version;	      

	public Integer getPurchaseOrderId() {
		return purchaseOrderId;
	}

	public void setPurchaseOrderId(Integer purchaseOrderId) {
		this.purchaseOrderId = purchaseOrderId;
	}

	public String getPurchaseOrderCode() {
		return purchaseOrderCode;
	}

	public void setPurchaseOrderCode(String purchaseOrderCode) {
		this.purchaseOrderCode = purchaseOrderCode;
	}

	public String getPurchaseOrderType() {
		return purchaseOrderType;
	}

	public void setPurchaseOrderType(String purchaseOrderType) {
		this.purchaseOrderType = purchaseOrderType;
	}

	public String getPurchaseOrderStatus() {
		return purchaseOrderStatus;
	}

	public void setPurchaseOrderStatus(String purchaseOrderStatus) {
		this.purchaseOrderStatus = purchaseOrderStatus;
	}

	public Date getPurchaseOrderDate() {
		return purchaseOrderDate;
	}

	public void setPurchaseOrderDate(Date purchaseOrderDate) {
		this.purchaseOrderDate = purchaseOrderDate;
	}

	public Vendor getVendor() {
		return vendor;
	}

	public void setVendor(Vendor vendor) {
		this.vendor = vendor;
	}

	public Department getAccessDepartment() {
		return accessDepartment;
	}

	public void setAccessDepartment(Department accessDepartment) {
		this.accessDepartment = accessDepartment;
	}

	public Location getLocation() {
		return location;
	}

	public void setLocation(Location location) {
		this.location = location;
	}
	
	public String getAssetType() {
		return assetType;
	}

	public void setAssetType(String assetType) {
		this.assetType = assetType;
	}


	public boolean isRepairPurchaseOrder()
	{
		return StringUtils.equalsIgnoreCase(PURCHASEORDERTYPE_REPAIR, purchaseOrderType);
	}
	
	public boolean isNewPurchaseOrder()
	{
		return StringUtils.equalsIgnoreCase(PURCHASEORDERTYPE_NEW, purchaseOrderType);
	}
	

	public List<PurchaseOrderDetail> getPurchaseOrderDetails() {
		return purchaseOrderDetails;
	}

	public void setPurchaseOrderDetails(
			List<PurchaseOrderDetail> purchaseOrderDetails) {
		this.purchaseOrderDetails = purchaseOrderDetails;
	}
	
	public PurchaseOrderDetail findPurchaseOrderDetails(AssetModel assetModel) {
		
		if(purchaseOrderDetails!=null)
		{
			for(int i=0;i<purchaseOrderDetails.size();i++)
			{
				AssetModel curAssetModel= purchaseOrderDetails.get(i).getAssetModel(); 
				int curAssetModelId = curAssetModel.getAssetModelId();
				int assetModelId = assetModel.getAssetModelId()==null?-1:assetModel.getAssetModelId().intValue();
				if(StringUtils.equalsIgnoreCase(assetModel.getAssetModelCode(), curAssetModel.getAssetModelCode()) || 
					curAssetModelId==assetModelId)
				{
					return purchaseOrderDetails.get(i); 
				}
			}
		}
		return null;
	}
	

	
	public PurchaseOrderRepair findPurchaseOrderRepairs(AssetModel assetModel,String serialNo) {
		
		if(purchaseOrderRepairs!=null)
		{
			for(int i=0;i<purchaseOrderRepairs.size();i++)
			{
				AssetModel curAssetModel= purchaseOrderRepairs.get(i).getAssetModel(); 
				int curAssetModelId = curAssetModel.getAssetModelId();
				int assetModelId = assetModel.getAssetModelId()==null?-1:assetModel.getAssetModelId().intValue();
				if((StringUtils.equalsIgnoreCase(assetModel.getAssetModelCode(), curAssetModel.getAssetModelCode()) || 
					curAssetModelId==assetModelId) && StringUtils.equalsIgnoreCase(purchaseOrderRepairs.get(i).getSerialNo(), serialNo))
				{
					return purchaseOrderRepairs.get(i); 
				}
			}
		}
		return null;
	}

	public List<PurchaseOrderRepair> getPurchaseOrderRepairs() {
		return purchaseOrderRepairs;
	}

	public void setPurchaseOrderRepairs(
			List<PurchaseOrderRepair> purchaseOrderRepairs) {
		this.purchaseOrderRepairs = purchaseOrderRepairs;
	}

	public String getPurchaseOrderDateToDisplay()
	{
		DateTimeFormatter fmt = DateTimeFormat.forPattern(GlobalConstant.DATE_FORMAT_JAVA);
		
		if(purchaseOrderDate!=null) return new LocalDate(purchaseOrderDate.getTime()).toString(fmt);
				
		return "";
	}
	
	public String getAuditContentHead()
	{
		Vendor ven = vendor;
		Location loc = location;
		if(vendor==null){
			ven = new Vendor();
		}
		if(location==null){
			loc = new Location();
		}
		return new ToStringBuilder(this,SpecialToStringStyle.SPECIAL_STYLE)
			.append("Code",purchaseOrderCode)
			.append("PO Date",getPurchaseOrderDateToDisplay())
			.append("Vendor", ven.getVendorId() + " " + ven.getVendorName())
			.append("PO OrderType",purchaseOrderType)
			.append("Asset Type",assetType)
			.append("Location", loc.getLocationCode() + " " + loc.getLocationName())
			.append("Company Code", companyCode!=null? companyCode:"")
			.toString();
	}
	
	public String getAuditContentDetail()
	{
		ToStringBuilder builder = new ToStringBuilder(this,SpecialMuLineToStringStyle.SPECIAL_MULINE_STYLE);
		if(purchaseOrderDetails!=null && CollectionUtils.isNotEmpty(purchaseOrderDetails))
		{
			int i = 0;
			for(PurchaseOrderDetail purchaseOrderDetail : purchaseOrderDetails)
			{
				if(!purchaseOrderDetail.isDeleted()){
					builder.append("Item " + (++i), purchaseOrderDetail.getAuditContentHead());
				}
			}
			String str = builder.toString();
			return StringUtils.substring(str, str.indexOf("[")+1, str.lastIndexOf("]")-1);
		}
		
		else if(purchaseOrderRepairs!=null && CollectionUtils.isNotEmpty(purchaseOrderRepairs))
		{
			int i = 0;
			for(PurchaseOrderRepair purchaseOrderRepair : purchaseOrderRepairs)
			{
				if(!purchaseOrderRepair.isDeleted()){
					builder.append("Item " + (++i), purchaseOrderRepair.getAuditContentHead());
				}
			}
			String str = builder.toString();
			return StringUtils.substring(str, str.indexOf("[")+1, str.lastIndexOf("]")-1);
		}
		return super.getAuditContentDetail();
	}

	public int getVersion() {
		return version;
	}
	
	public String getAuditCode()
	{
		if(StringUtils.isNotEmpty(purchaseOrderCode)){
			return purchaseOrderCode;
		}
		return super.getAuditCode();
	}

	public void setVersion(int version) {
		this.version = version;
	}

	public static final String PURCHASEORDERTYPE_NEW="NEW";
	public static final String PURCHASEORDERTYPE_REPAIR="REPAIR";
	
	public static final String PURCHASEORDERSTATUS_NEW="NEW";
	public static final String PURCHASEORDERSTATUS_INPROCESS="INPROCESS";
	public static final String PURCHASEORDERSTATUS_CLOSED="CLOSED";
	
}
